package com.zpb.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zpb.admin.domain.dto.MenuQueryDto;
import com.zpb.framework.domain.entity.RoleMenu;
import com.zpb.framework.mapper.RoleMenuMapper;
import com.zpb.framework.domain.vo.MenuTreeSelectVo;
import com.zpb.admin.domain.vo.MenuVo;
import com.zpb.admin.service.MenuService;
import com.zpb.framework.domain.ApiResult;
import com.zpb.framework.domain.entity.Menu;
import com.zpb.framework.domain.enums.ResultCodeEnum;
import com.zpb.framework.mapper.MenuMapper;
import com.zpb.framework.utils.BeanCopyUtil;
import com.zpb.framework.utils.DictCodeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: zhaopengbo
 * @Date: 2025/9/21
 */
@Service
public class MenuServiceImpl implements MenuService {
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public ApiResult<List<MenuVo>> getMenuListByCondition(MenuQueryDto menuQueryDto) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<Menu>();
        queryWrapper.like(menuQueryDto.getMenuName() != null && menuQueryDto.getMenuName() != "", Menu::getMenuName, menuQueryDto.getMenuName())
                .eq(menuQueryDto.getStatus() != null, Menu::getStatus, menuQueryDto.getStatus())
                .orderByAsc(Menu::getParentId)
                .orderByAsc(Menu::getOrderNum);

        List<Menu> menus = menuMapper.selectList(queryWrapper);
        List<MenuVo> menuVos = BeanCopyUtil.copyBeanList(menus, MenuVo.class);
        return ApiResult.success(menuVos);
    }

    @Override
    public ApiResult addMenu(Menu menu) {
        int result = menuMapper.insert(menu);
        if (result == 0) {
            return ApiResult.error(ResultCodeEnum.ADD_FAILURE);
        }
        return ApiResult.success(result);
    }

    @Override
    public ApiResult<MenuVo> getMenuById(Long id) {
        Menu menu = menuMapper.selectById(id);
        if (menu == null) {
            return ApiResult.failure(ResultCodeEnum.NO_MENU);
        }
        return ApiResult.success(BeanCopyUtil.copyBean(menu, MenuVo.class));
    }

    @Override
    public ApiResult updateMenuById(Menu menu) {
        if (menu.getParentId().equals(menu.getId()) || menu.getParentId() == menu.getId()) {
            return ApiResult.failure(ResultCodeEnum.UPDATE_FAILURE.getCode(), "修改菜单‘" + menu.getMenuName() + "’失败，上级菜单不能选择自己");
        }
        int result = menuMapper.updateById(menu);
        if (result == 0) {
            return ApiResult.error(ResultCodeEnum.UPDATE_FAILURE);
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult deleteMenuById(Long id) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId, id);
        Long count = menuMapper.selectCount(queryWrapper);
        if (count != 0) {
            return ApiResult.failure(ResultCodeEnum.EXIST_CHILDREN_MENU);
        }

        int result = menuMapper.deleteById(id);
        if (result == 0) {
            return ApiResult.error(ResultCodeEnum.DEL_FAILURE);
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult<List<MenuTreeSelectVo>> getMenuTreeSelect() {

        List<MenuTreeSelectVo> menuTreeSelectVos = menuMapper.selectMenuTree(null);
        List<MenuTreeSelectVo> parentMenuTreeVo = menuTreeSelectVos.stream()
                .filter(m -> Objects.equals(m.getParentId(),0L))
                .collect(Collectors.toList());
        parentMenuTreeVo.forEach(m -> {
            m.setChildren(buildMenuTree(m.getId(), menuTreeSelectVos));
        });

        return ApiResult.success(parentMenuTreeVo);
    }


    @Override
    public List<Long> getCheckedKeysByRoleId(Long roleId) {

        List<RoleMenu> roleMenus =null;
        if (Objects.equals(roleId, DictCodeUtil.IS_ADMIN)) {
            List<Menu> menus = menuMapper.selectList(null);
            List<Long> menuKeys = menus.stream()
                    .map(Menu::getId)
                    .toList();
            return menuKeys;
        }else{
            LambdaQueryWrapper<RoleMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(RoleMenu::getRoleId,roleId);
            roleMenus = roleMenuMapper.selectList(queryWrapper);
        }

        List<Long> menuKeys = roleMenus.stream()
                .map(RoleMenu::getMenuId)
                .distinct()
                .collect(Collectors.toList());
        return menuKeys;
    }


    public List<MenuTreeSelectVo> buildMenuTree(Long parentId, List<MenuTreeSelectVo> menuTreeSelectVos) {
        List<MenuTreeSelectVo> children = menuTreeSelectVos.stream()
                .filter(m -> Objects.equals(m.getParentId(),parentId))
                .collect(Collectors.toList());
        children.stream()
                .forEach(m -> {
                    m.setChildren(buildMenuTree(m.getId(), menuTreeSelectVos));
                });
        return children;
    }
}
